package logic;

import java.util.Vector;

import data.*;

public class CompressionAlgorithm extends Algorithm {

	//TODO find out the real numbers!!!!!!!!!!!
	private final int threshold=0;     // num of IO that an unactive LUN does
	private final double diskSize=Data.SCSIDiskSize;
	private final double diskThroughput=Data.SCSITHROUGHPUT;  // data transfer rate
	private final double diskLatency=Data.SCSILATENCY;         // overhead for each IO

    @Override
	public GraphData compute( AlgorithmInput input, Data data) {

		double memSize=0;
		Vector<CompressionGraphObject> vec=new Vector<CompressionGraphObject>();
		int[] unActive = data.getUnactiveLUNs(threshold);

		for(int i=0; i< unActive.length; i++){
			LUN l=data.getLUN(unActive[i]);
			memSize+=l.get_size();
		}
		
		double tmp=memSize/diskSize;
		int emptyDisks;
		if((int)tmp<tmp)
			emptyDisks=(int)tmp+1;
		else emptyDisks=(int)tmp;
		 
		//minimum number of empty disks
		double oldDisksAmount=data.getTotalSize()/diskSize; 
				
		for(int diskAmount=0; diskAmount<=emptyDisks; diskAmount++){
			double performance = computePerformance(data, oldDisksAmount-diskAmount);
			vec.add(new CompressionGraphObject(diskAmount, performance));
		}

		CompressionGraphData ans= new CompressionGraphData(vec);
		return ans;
	}

	private double computePerformance(Data data, double diskAmount){
		double IOkb, IOnum, time, e, u;
		double performances=0;
		int ios=0;

		for(int i=1; i<data.getNumOfTimeUnits(); i++){
			TimeUnit tu=data.getTimeUnit(i);
			int tusize=tu.get_timesize();
				IOkb=tu.get_totalKbWritten()+tu.get_totalKbRead();
				IOnum=tu.get_numReads()+tu.get_numWrites();
				ios+=IOnum;

				time=tusize*diskAmount;
				e=(IOkb/diskThroughput) + (IOnum*diskLatency);
				u=e/time;
				if(u>0.8)
					return -1;
				performances+=e/(1-u);
		}

		Double performance=performances/ios;
		return performance;
	}



}
